﻿//
// *************************************************************************************
// WP-Framework
//
// Developed by 
// Lukas Kretschmar (lkretschmar.dev@bluewin.ch)
//
// Switzerland, Copyright (c) 2013 lkretschmar
// This content is released under the MIT License (http://opensource.org/licenses/MIT).
//     
// *************************************************************************************
//
//
			

using System;
using KretschIT.WP_Fx.EasyMoq.Calls.Collections.Items;
using System.Linq.Expressions;
using KretschIT.WP_Fx.Core.Extensions;
using KretschIT.WP_Fx.EasyMoq.Calls.Collections;
using KretschIT.WP_Fx.Core.Validation;
using System.Linq;
using System.Collections.Generic;

namespace KretschIT.WP_Fx.EasyMoq.Calls
{
    internal class CallHandler<TSetupHandler, TSetupItem> : ICallHandler<TSetupHandler, TSetupItem> where TSetupHandler : new() where TSetupItem : class, ICallItem
    {
        private readonly ICallCollection<TSetupItem> setups = new CallCollection<TSetupItem>();
        private readonly ICallCollection<IMethodCallItem> calls = new CallCollection<IMethodCallItem>();

        private Func<MethodCallExpression, TSetupHandler, TSetupItem> createItem;

        public CallHandler(Func<MethodCallExpression, TSetupHandler, TSetupItem> createItem)
        {
            It.IsNotNull(() => createItem);

            this.createItem = createItem;
        }

        public TSetupHandler Setup(LambdaExpression call)
        {
            It.IsNotNull(() => call);

            var setupHandler = new TSetupHandler();
            var item = this.createItem(call.To<MethodCallExpression>(), setupHandler);
            this.setups.Add(item);
            return setupHandler;
        }

        public IEnumerable<TSetupItem> Call(LambdaExpression call)
        {
            It.IsNotNull(() => call);

            var methodCall = call.To<MethodCallExpression>();
            this.calls.Add(new MethodCallItem(methodCall));
            return this.setups.GetMatches(methodCall);
        }

        public int Calls(LambdaExpression call)
        {
            It.IsNotNull(() => call);

            return this.calls.GetMatches(call.To<MethodCallExpression>()).Count();        
        }
    }
}
